<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>1.7. 块级函数（Block-Level Functions）</title>
</head>
<body>

</body>
<script>
    /*
    在 ECMAScript 5 中，这段代码会抛出语法错误。然而 ECMAScript 6 会将 doSomething() 函数视为块级声明并可以在块内的其它部分调用，例如：
     */
    "use strict";

    if (true) {

        console.log(typeof doSomething);        // "function"

        function doSomething() {
            // ...
        }

        doSomething();
    }

    console.log(typeof doSomething);            // "undefined"

    // =================================1.7.1. 使用块级函数的时机（Deciding When to Use Block-Level Functions）=======================
    // 块级函数与 let 函数表达式的相似之处是它们都会在执行流跳出定义它们所在的块作用域之后被销毁。
    // 关键的区别是块级函数（声明）会被提升到顶部，而 let 函数表达式则不会，以下代码对其做了说明：
    /*
    "use strict";

    if (true) {

        console.log(typeof doSomething);        // 抛出错误

        let doSomething = function () {
            // ...
        }

        doSomething();
    }

    console.log(typeof doSomething);
     */
    // 在这里，代码执行到 typeof doSomething 回戛然而止，因为 let 语句还未被执行，doSomething() 仍处在 TDZ 内部。
    // 了解改差异之后，你可以根据是否想让函数提升到顶部来选择块级函数（声明）或 let 函数表达式。

    //==================================1.7.2. 非严格模式下的块级函数（Block-Level Functions in Nonstrict Mode）========================
    /*
    ECMAScript 6 同样允许非严格模式下块级函数的存在，但是具体行为有些不同。
    函数的声明会被提升至函数作用域或全局作用域的顶部，而不是块内。例如：

    // ECMAScript 6 的行为
    if (true) {

        console.log(typeof doSomething);        // "function"

        function doSomething() {
            // ...
        }

        doSomething();
    }

    console.log(typeof doSomething);            // "function"
    在本例中，doSomething() 会被提升至全局作用域的顶部，所以在 if 代码块外它仍然存在。
    ECMAScript 6 标准化了该行为以消除不同浏览器之间存在的差异，
    于是在所有 ECMASCript 6 运行环境中该表现都是相同的。

    允许在 JavaScript 中声明块级变量使得声明函数的能力得到了加强。然而 ECMAScript 6 还引入了另一种全新的声明函数的方法。
     */

</script>
</html>
